package cn.sccl.common.database;


import cn.sccl.common.model.QueryData;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.Serializable;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;

/**
 * Created by 杨浩宇 on 2016-02-18.
 */
public class DataSet implements Serializable {

    /**
     *
     */
    private static final long serialVersionUID = 7685857145867509064L;
    private static Log log = LogFactory.getLog(DataSet.class);
    /**
     * 该数据包含的表名
     */
    public String[] TABLE_NAMEs = null;
    /**
     * 数据集名称
     */
    public String Name = "";
    /**
     * 字段名和对应的列索引
     */
    public HashMap<String, Integer> FieldsIndex = new HashMap<String, Integer>();
    /**
     * 所有列名
     */
    public String[] columnsNames = null;
    /**
     * 列类型，用从0开始的下标值获取
     */
    public String[] ColumnsType = null;
    /**
     * 行总数
     */
    public long RowCount = 0;
    /**
     * 列总数
     */
    public int ColumnsCount = 0;
    /**
     * 未分页的SQL语句
     */
    public String SQLNoPaging = "";
    /**
     * 查询返回的数据集行对象
     */
    private ArrayList<DataRow> Rows = new ArrayList<DataRow>(15);

    /**
     * 将单条记录填充到HashMap中
     *
     * @param rs
     */
    public static QueryData FillHashMap(ResultSet rs) {
        ResultSetMetaData rsmd = null;
        QueryData hsStore = new QueryData();
        try {
            // 如果是空记录值，则返回，否则定位到第一条记录
            if (rs.isAfterLast() || (rs.next() && rs.isAfterLast()))
                return hsStore;

            // 初始化查询结果中的列名
            rsmd = rs.getMetaData();
            int iColumnCount = rsmd.getColumnCount();
            // 定义字段名称数组
            String[] aryFieldName = new String[iColumnCount];
            // 定义字段日期类型数组
            Boolean[] aryBooleans = new Boolean[iColumnCount];

            for (int iIdx = 0; iIdx < iColumnCount; iIdx++) {
                aryFieldName[iIdx] = rsmd.getColumnLabel(iIdx + 1);
                if (rsmd.getColumnTypeName(iIdx + 1).equals("DATE")
                        || rsmd.getColumnTypeName(iIdx + 1).equals("TIMESTAMP"))
                    aryBooleans[iIdx] = true;
                else
                    aryBooleans[iIdx] = false;
            }

            DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

            for (int iIdx = 0; iIdx < iColumnCount; iIdx++) {
                Object objTemp = rs.getObject(iIdx + 1);
                // 如果是日期型，格式化标准的格式化
                if (aryBooleans[iIdx] == true) {
                    if (objTemp == null)
                        objTemp = "";
                    else {
                        try {
                            java.util.Date dt = df.parse(objTemp.toString());
                            objTemp = df.format(dt);
                        } catch (ParseException e) {
                            log.fatal("日期转换错误，" + e.getMessage());
                        }
                    }
                }
                hsStore.put(aryFieldName[iIdx], objTemp);
            }

        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return hsStore;
    }

    /**
     * 将查询出的数据集转换成DataSet对象
     *
     * @param rs
     */
    public static DataSet FillDataSet(ResultSet rs) {
        DataSet ds = new DataSet();
        ResultSetMetaData rsmd = null;
        try {
            // 清除所内容
            ds.Clear();
            ds.FieldsIndex.clear();

            // 初始化查询结果中的列名
            rsmd = rs.getMetaData();
            int iColumnCount = rsmd.getColumnCount();

            ds.ColumnsType = new String[iColumnCount];
            ds.columnsNames = new String[iColumnCount];
            ds.ColumnsCount = iColumnCount;

            for (int iIdx = 0; iIdx < iColumnCount; iIdx++) {
                String strFieldName = rsmd.getColumnLabel(iIdx + 1);
                ds.FieldsIndex.put(strFieldName, iIdx);
                ds.columnsNames[iIdx] = strFieldName;
                ds.ColumnsType[iIdx] = rsmd.getColumnTypeName(iIdx + 1);
            }

            // 得到行数
            // rs.last();
            // int iRowCount = rs.getRow();
            // rs.beforeFirst();
            // ds.Rows.ensureCapacity(iRowCount);

            // 初始化每行
            long lRowCount = 0;
            while (rs.next()) {
                DataRow dRow = new DataRow(ds);
                dRow.InitDataRow(rs, iColumnCount);
                ds.AddRow(dRow);
                lRowCount++;
                // 最大输出只能是10000条记录
//                if (lRowCount > 10000)
//                    break;
            }

            ds.RowCount = lRowCount;
            ds.ColumnsCount = iColumnCount;
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return ds;
    }

    /**
     * 用默认的DataRow
     */
    public DataRow AddRow() {
        DataRow ds = new DataRow(this);
        ds.InitDataRow(null, this.ColumnsCount);
        this.Rows.add(ds);
        this.RowCount++;
        return ds;
    }

    public DataRow AddRow(int index) {
        DataRow ds = new DataRow(this);
        ds.InitDataRow(null, this.ColumnsCount);
        this.Rows.add(index, ds);
        this.RowCount++;
        return ds;
    }

    /**
     * 新增行
     *
     * @param dRow
     */
    public void AddRow(DataRow dRow) {
        this.Rows.add(dRow);
        this.RowCount++;
    }

    /**
     * 新增在指定的位置新增行
     *
     * @param dRow
     * @param iIdx
     */
    public void AddRow(int iIdx, DataRow dRow) {
        this.Rows.add(iIdx, dRow);
        this.RowCount++;
    }

    public void Clear() {
        this.Rows.clear();
        this.RowCount = 0;
        this.ColumnsCount = 0;
        this.ColumnsType = null;
    }

    public void clearRow() {
        this.Rows.clear();
        this.RowCount = 0;
    }

    /**
     * @param aryColumnsName
     */
    public void setColumnsName(String[] aryColumnsName) {
        this.columnsNames = aryColumnsName;
        this.ColumnsCount = aryColumnsName.length;
        FieldsIndex.clear();
        for (int iIdx = 0; iIdx < aryColumnsName.length; iIdx++) {
            FieldsIndex.put(aryColumnsName[iIdx], iIdx);
        }
        if (this.ColumnsType != null) {
            // 列类型定义
            String[] ColumnsTypeTemp = new String[this.ColumnsCount];
            System.arraycopy(this.ColumnsType, 0, ColumnsTypeTemp, 0, this.ColumnsType.length);
            this.ColumnsType = null;
            this.ColumnsType = ColumnsTypeTemp;
        }

        // 复制行的数据到扩展后的行数据
        for (int iRow = 0; iRow < this.Rows.size(); iRow++) {
            DataRow dRow = this.Row(iRow);
            Object[] objTemp = new Object[aryColumnsName.length];
            System.arraycopy(dRow.getColumnsObjects(), 0, objTemp, 0, dRow.getColumnsObjects().length);
            dRow.setColumnsObjects(objTemp);
        }
    }

    /**
     * @param aryColumnsName
     */
    public void setColumnsName(Object[] aryColumnsName) {
        this.columnsNames = new String[aryColumnsName.length];
        this.ColumnsCount = aryColumnsName.length;
        FieldsIndex.clear();
        for (int iIdx = 0; iIdx < aryColumnsName.length; iIdx++) {
            this.columnsNames[iIdx] = (String) aryColumnsName[iIdx];
            FieldsIndex.put(this.columnsNames[iIdx], iIdx);
        }
        if (this.ColumnsType != null) {
            // 列类型定义
            String[] ColumnsTypeTemp = new String[this.ColumnsCount];
            System.arraycopy(this.ColumnsType, 0, ColumnsTypeTemp, 0, this.ColumnsType.length);
            this.ColumnsType = null;
            this.ColumnsType = ColumnsTypeTemp;
        }

        // 复制行的数据到扩展后的行数据
        for (int iRow = 0; iRow < this.Rows.size(); iRow++) {
            DataRow dRow = this.Row(iRow);
            Object[] objTemp = new Object[aryColumnsName.length];
            System.arraycopy(dRow.getColumnsObjects(), 0, objTemp, 0, dRow.getColumnsObjects().length);
            dRow.setColumnsObjects(objTemp);
        }

    }

    /**
     * 获取指定行，下标从0开始
     *
     * @param iRowIdx 行索引
     * @return
     */
    public DataRow getRow(int iRowIdx) {
        return this.Rows.get(iRowIdx);
    }

    /**
     * 获取指定行，下标从0开始
     *
     * @param iRowIdx 行索引
     * @return 行DataRow
     */
    public DataRow Row(int iRowIdx) {
        return this.Rows.get(iRowIdx);
    }

}
